%% 配置文件加载和处理的模块。它做为一个gen_server独立运行，可以通过向它发取{get,xxx}，得到对应的配置信息。
%% 配置文件的路径由启动时的config变量来指定。
%% 配置文件参见xbt.cfg文件。

-module(xbt_config).

-behaviour(gen_server).

-export([get_config/1]).
-export([init/1,handle_call/3,handle_cast/2,
         handle_info/2,terminate/2,code_change/3]).
-export([start_link/0]).

-include("xbt.hrl").

get_config(Params)     ->
    gen_server:call(?MODULE,{get,Params}).

start_link()           ->
    gen_server:start_link({local,?MODULE},?MODULE,[],[]).

init([])  ->
    case application:get_env(config) of
        {ok,Conf}       ->
            parse_config(Conf);
        undefined       ->
            ?DEBUG("[~p]no config,use defaults~n",[self()]),
            {ok,#config{}}
    end.

terminate(_, _State) ->
    ok.

handle_cast(_Msg, State) ->
    {noreply,State}.

handle_call({get,bootnodes},_From,State)    ->
    {reply,State#config.bootnodes,State};

handle_call({get,storage_mod},_From,State)     ->
    {reply,State#config.storage_mod,State};

handle_call({get,datafile},_From,State)     ->
    {reply,State#config.datafile,State};

handle_call({get,access},_From,State)         ->
    {reply,State#config.access,State};

handle_call({get,users},_From,State)        ->
    {reply,State#config.users,State};

handle_call(_Msg,_From,State) ->
    {reply,ok,State}.

handle_info(_Info, State) ->
    {noreply, State}.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

parse_config(Conf)   ->
    ?DEBUG("[~p]try to parse config file:~p~n",[self(),Conf]),
    case file:consult(Conf) of
        {ok, Terms}       ->
            Res = lists:foldl(fun process_term/2, #config{}, Terms),
            {ok, Res};
        {error,Reason}    ->
            ?DEBUG("[~p]Can't load config file: ~p~n",[self(),Conf]),
            {error,Reason}
    end.

process_term(Term, Config)  ->
    case Term of
        {access, Access}  ->
            Config#config{access = Access};
        {datafile, File}    ->
            Config#config{datafile = File};
        {users,Users}       ->
            Config#config{users = Users};
        {bootnodes,Nodes}   ->
            Config#config{bootnodes = Nodes};
        {storage_mod,Mod}   ->
            Config#config{storage_mod = Mod};
        _Other              ->
            Config
    end.

